require("dotenv").config();
const Koa = require("koa");
const bodyParser = require("koa-bodyparser");
const cors = require("@koa/cors");
const swaggerJSDoc = require("swagger-jsdoc");
const { koaSwagger } = require("koa2-swagger-ui");
const routes = require("./routes/index");
const errorHandler = require("./middlewares/errorHandler");
const authMiddleware = require("./middlewares/authMiddleware");

const { writeLog } = require('./utils/index');

const app = new Koa();
const net = require('net');
const { exec } = require('child_process');

// Log run info to file
writeLog('run', 'Application started');

// 中间件配置
app.use(cors());
app.use(errorHandler);
app.use(bodyParser());

// 认证中间件
app.use(
  authMiddleware.unless({
    path: [
      /^\/system\/login/, // 登录接口
      /^\/system\/register/, // 注册接口
      /^\/system\/checkusername/, // 检查用户名接口
      /^\/system\/departments/, // 部门下拉接口
      /^\/system\/encodePwd/, // 密码加密接口测试用
      /^\/docs/, // Swagger 文档路径
    ],
  })
);

// Swagger 配置
const swaggerDefinition = {
  openapi: "3.0.0",
  info: {
    title: "User and Department API",
    version: "1.0.0",
  },
  components: {
    schemas: {
      Dept: {
        type: "object",
        properties: {
          id: {
            type: "string",
            format: "uuid",
            description: "部门ID",
          },
          deptName: {
            type: "string",
            description: "部门名称",
          },
          parentDeptId: {
            type: "string",
            format: "uuid",
            description: "父部门ID",
          },
          fullId: {
            type: "string",
            description: "完整部门ID路径",
          },
          fullDeptName: {
            type: "string",
            description: "完整部门名称路径",
          },
          delete: {
            type: "boolean",
            description: "是否删除",
          },
          createBy: {
            type: "string",
            description: "创建人",
          },
          createDate: {
            type: "string",
            format: "date-time",
            description: "创建时间",
          },
          updateBy: {
            type: "string",
            description: "更新人",
          },
          updateDate: {
            type: "string",
            format: "date-time",
            description: "更新时间",
          },
          status: {
            type: "string",
            description: "状态",
          },
        },
      },
    },
  },
};

const options = {
  swaggerDefinition,
  apis: ["./src/routes/*.js"],
};

const swaggerSpec = swaggerJSDoc(options);

// 确保 Swagger 中间件在路由之前加载
app.use(
  koaSwagger({
    routePrefix: "/docs",
    exposeSpec: true,
    swaggerOptions: {
      spec: swaggerSpec,
      validatorUrl: null,
    },
  })
);

// 路由配置
app.use(routes);

// 端口处理逻辑
function isPortAvailable(port) {
  return new Promise((resolve) => {
    const server = net.createServer().listen(port);
    server.on('error', () => resolve(false));
    server.on('listening', () => {
      server.close();
      resolve(true);
    });
  });
}

async function killProcessOnPort(port) {
  return new Promise((resolve, reject) => {
    exec(`netstat -ano | findstr :${port}`, (error, stdout) => {
      if (error) {
        reject(error);
        return;
      }

      const lines = stdout.split('\n');
      for (const line of lines) {
        const match = line.trim().split(/\s+/);
        if (match.length >= 5) {
          const pid = match[4];
          exec(`taskkill /PID ${pid} /F`, (err) => {
            if (err) {
              reject(err);
            } else {
              resolve();
            }
          });
          return;
        }
      }
      reject(new Error(`No process found on port ${port}`));
    });
  });
}

async function findAvailablePort(startPort) {
  const port = startPort;
  if (!await isPortAvailable(port)) {
    console.log(`端口 ${port} 被占用，尝试结束占用进程...`);
    try {
      await killProcessOnPort(port);
      console.log(`端口 ${port} 的占用进程已结束。`);
    } catch (error) {
      console.error(`无法结束端口 ${port} 的占用进程:`, error.message);
      process.exit(1);
    }
  }
  return port;
}

// 启动服务
const port = process.env.PORT || 6686;
(async () => {
  const availablePort = await findAvailablePort(port);
  const server = app.listen(availablePort, () => {
    console.log("Server running on http://localhost:" + availablePort);
  });

  // 捕获信号以正确关闭服务
  process.on('SIGINT', () => {
    server.close(() => {
      writeLog('run', 'Server is gracefully shutting down (SIGINT)');
      console.log('Server is gracefully shutting down');
      process.exit(0);
    });
  });

  process.on('SIGTERM', () => {
    server.close(() => {
      writeLog('run', 'Server is gracefully shutting down (SIGTERM)');
      console.log('Server is gracefully shutting down');
      process.exit(0);
    });
  });
})();
